package glb;

import java.awt.Color;
import robocode.HitWallEvent;
import robocode.Robot;
import robocode.ScannedRobotEvent;
import static robocode.util.Utils.normalRelativeAngleDegrees;

/**
 * A simple robot that scans continuously, hugs the walls,
 * and shoots bullets proportional to an enemy's distance.
 * 
 * @author Gregory Burgess
 * @version 1.0
 * 
 * Movement algorithm based on sample.Walls Copyright 
 * (c) 2001, 2010 Mathew A. Nelson and Robocode contributors
 */
public class Failbot extends Robot {
  //keeps track of initialization
  boolean init = true;
  //field size
  double fieldWidth;
  double fieldHeight;

  /**
  * Tells the robot to scan continuously and move.
  */
  public void run() {
    if (init) {
      fieldWidth = getBattleFieldWidth();
      fieldHeight = getBattleFieldWidth();
      //fashion decisions
      this.setBulletColor(Color.green);
      this.setRadarColor(Color.white);
      
      //make it so that the gun and radar don't turn 
      //when we turn.
      setAdjustRadarForRobotTurn(false);
      setAdjustGunForRobotTurn(false);
     
      //look for targets to shoot
      turnRadarRight(360);
      //go to top left corner to start
      goTo(0,fieldHeight);
    } 
    
    while (true) {
      //scoot n shoot!
      turnRadarRight(360);
      ahead(300);
    } 
  } 
  /**
   * Handles wall collisions.
   * @param e - A Robocode event.
   */  
  public void onHitWall(HitWallEvent e) { 
    //turn "right"
    if (init) { 
      turnRight(180 - (getHeading() % 90));
      init = false;
    } 
    else { 
      turnRadarRight(360);
      turnRight(90);
      ahead(300);
      turnRadarRight(360);
    }
  } 
  
  
  /**
  * Figures out if the opponent is close enough, and shoots at them if they are.
  * @param e - A Robocode event that holds enemy data.
  */
  public void onScannedRobot(ScannedRobotEvent e) {
    turnGunRight(toTurn(e, getHeading(), getGunHeading()));
    //Only shoot at close, slow opponents
      fire(getPow(e)); 
    //run away after you shoot
    ahead(100);
    turnRadarRight(360);
  } 
  
  /**
   * Returns the angle the robot should turn its gun to engage the enemy.
   * @param e a Robocode event
   * @param heading robot's heading
   * @param gunHeading robot's gun's heading
   * @return the degrees to turn right to engage the enemy
   */
  public double toTurn(ScannedRobotEvent e, double heading, double gunHeading) { 
    //Turns the gun to the bearing of the scanned robot
      //getHeading()-getGunHeading = the offset of the gun from the robots heading.
      //e.getBearing= the angle to the robot between -180 (on the robots left flank) 
      //and 180 (robots right flank) normalRelativeAngleDegrees() returns a number between
      // -180 and 180, given a number between 0 and 360
    double temp = heading - gunHeading + e.getBearing();
    return normalRelativeAngleDegrees(temp);
  } 
    
  /**
   * Returns the power the robot should use on a shot, 
   * based on enemy proximity, direction, and speed.
   * @param e - A Robocode event that holds enemy data.
   * @return - a double representing the power the robot should use for its shot.
   */
  public double getPow(ScannedRobotEvent e) { 
    //if theyr'e against a wall, or directly on our flank, or very close, or very slow,
    //Shoot hard.
    if (e.getVelocity() < 2 || e.getDistance() < 200 || e.getBearing() % 90 == 0) { 
      return 3;
    } 
    //else shoot a shot proportional to the opponent's distance.
    else { 
      double i = 0;
      //other robot's distance
      double dist = e.getDistance();
       i = dist / 125.0;
       i = 5 - i;
       return i;
    } 
  } 
  
  /**
   * Move a robot to a point on the battlefield.  Really, this only sorta works
   * to move the robot to the top left corner.
   * @param x x coordinate
   * @param y y coordinate
   */
  public void goTo(double x, double y) {
    turnLeft(getHeading());
    turnLeft(getTurn(x,y));
    ahead(getDist(x,y));
  }
    
  
  /**
   * Returns the angle the bot should turn left to get to the point.
   * @param x x coordinate.
   * @param y y coordinate.
   * @return angle to turn left.
   */
  public double getTurn(double x, double y) { 
    double myX = getX();
    double myY = getY();
    //get distances between points
    double deltaX = Math.abs(myX - x);
    double deltaY = Math.abs(myY - y);
    //accounts for body width at extreme angles
    if (myX + myY < fieldHeight) { 
      deltaY -= 20 - 20 * myX / fieldWidth;
    } 
    //Calculates theta with respect to the bot.
    double angle = Math.atan((deltaX / deltaY));
    angle  = Math.toDegrees(angle);
    //accounts for body width at extreme angles
    if (myX + myY > fieldHeight) { 
      angle *= 1.3;
    }
    out.println(angle);
    return angle;
  }
  
  /**
   * Returns the distance to x,y.
   * @param x x coordinate.
   * @param y y coordinate
   * @return the dist to the specified point.
   */
  public double getDist(double x, double y) {
    //Pythagorean theorem
    double deltaX = Math.abs(x - this.getX());
    double deltaY = Math.abs(y - this.getY());
    double dist =  Math.sqrt(deltaX * deltaX + deltaY * deltaY);
    out.println(dist);
    return dist;
  }
  
} 
  